package val.to.entities;

import java.io.Serializable;
import java.util.Date;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.Parcel;
import android.os.Parcelable;
import val.to.Utility;
import val.to.server.JsonUtils;

/**
 * Represents a single Valto event.
 */
public class Event implements Serializable, Parcelable {

	public class StateSync {
		public void doSync(EventState state) {
			state.checkedIn = m_isCheckedInto;
			// TODO:
			// state.shared = m_isShared;
		}
	}

	private static final long serialVersionUID = -902725869991928598L;
	public static final int TEMP_ID = -1;
	public static final String NO_PASSWORD = "0";

	private int m_id;
	private double m_long;
	private double m_lat;
	private String m_name;
	private String m_desc;
	private Date m_startTime;
	private Date m_endTime;
	private int m_checkedInUsers;
	private boolean m_isShared; // by the current user
	private boolean m_isCheckedInto; // by the current user
	private String m_password = NO_PASSWORD;

	/**
	 * Internal ctor
	 * 
	 * @param id
	 * @param location
	 * @param name
	 * @param description
	 * @param type
	 */
	private Event(int id, String name, String description, double longitude,
			double latidude, Date startAt, Date endAt,
			int checkedInUsers, String password) {
		m_id = id;
		m_long = longitude;
		m_lat = latidude;
		m_name = name;
		m_desc = description;
		m_startTime = startAt;
		m_endTime = endAt;
		m_checkedInUsers = checkedInUsers;
		m_password = password;
	}

	public boolean isNew() {
		return m_id == TEMP_ID;
	}

	/**
	 * Gets the unique id of the event.
	 */
	public int getId() {
		return m_id;
	}

	/**
	 * Gets the name of the event.
	 */
	public String getName() {
		return m_name;
	}

	/**
	 * Gets the description of the event.
	 */
	public String getDescription() {
		return m_desc;
	}

	public int getCheckedInUsers() {
		return m_checkedInUsers;
	}

	public String getPassword() {
		return m_password;
	}

	/**
	 * Gets the start date of the event.
	 */
	public Date getStartDate() {
		return m_startTime;
	}

	/**
	 * Gets the end date of the event.
	 */
	public Date getEndTime() {
		return m_endTime;
	}

	public double getLongitude() {
		return m_long;
	}

	public double getLatitude() {
		return m_lat;
	}

	@Override
	public String toString() {
		return String.format("Event #%d: %s", m_id, m_name);
	}

	@Override
	public boolean equals(Object o) {
		if (o == null)
			return false;
		if (this == o)
			return true;
		if (!(o instanceof Event))
			return false;

		return ((Event) o).getId() == this.getId();
	}

	// TODO: implement getHashCode();
	private void assignUserFields(boolean isCheckedInto, boolean isShared) {
		m_isCheckedInto = isCheckedInto;
		m_isShared = isShared;
	}

	public static Event FromJson(JSONObject json) throws JSONException {
		int id = json.getInt("id");
		String name = json.getString("name");
		String desc = json.getString("description");
		double lon = json.getDouble("location_lon");
		double lat = json.getDouble("location_lat");
		String strStart = json.getString("start_date");
		String strEnd = json.getString("end_date");
		int checkedIn = json.getInt("numOfUsersCheckedIn");
		String password = json.getString("password");

		Event event = new Event(id, name, desc, lon, lat,
				JsonUtils.dateFromJson(strStart),
				JsonUtils.dateFromJson(strEnd),
				checkedIn, password);

		boolean isShared = false; // json.getBoolean("is_shared");
		boolean isCheckedInto = json.getBoolean("userCheckedIn");
		event.assignUserFields(isCheckedInto, isShared);
		return event;
	}

	public static Event NewEvent(String name, String description,
			double longitude, double latidude, Date startAt, Date endAt) {

		return new Event(TEMP_ID, name, description, longitude, latidude,
				startAt, endAt, -1, NO_PASSWORD);
	}

	public static Event UpdatedEvent(int id, String name, String description,
			double longitude, double latidude, Date startAt, Date endAt) {

		return new Event(id, name, description, longitude, latidude, startAt,
				endAt, -1, NO_PASSWORD);
	}

	public static Event NewEvent(String name, String description,
			double longitude, double latidude, Date startAt, Date endAt, String Password) {

		return new Event(TEMP_ID, name, description, longitude, latidude,
				startAt, endAt, -1, Utility.md5(Password));
	}

	public void finalizeEvent(JSONObject json) throws JSONException {
		m_id = json.getInt("id");
		m_checkedInUsers = json.getInt("numOfUsersCheckedIn");
		m_isCheckedInto = json.getBoolean("userCheckedIn");
	}

	public JSONObject json() throws JSONException {
		JSONObject json = new JSONObject();

		if (m_id != TEMP_ID){
			json.put("id", m_id);
		}
		
		json.put("name", m_name);
		json.put("description", m_desc);
		json.put("location_lon", m_long);
		json.put("location_lat", m_lat);
		json.put("start_date", JsonUtils.jsonDateFormatToUtc(m_startTime));
		json.put("end_date", JsonUtils.jsonDateFormatToUtc(m_endTime));
		json.put("radius", 1000);// TEMP: 1000 km rad
		json.put("password", m_password);

		return json;
	}

	// TODO:
	// Consider adding:
	// 1. Valto Activity Level (based on other users valto activity)
	// 2. Friends count (based on FB friends).

	// Parcelable implementation

	public void writeToParcel(Parcel out, int flags) {
		out.writeInt(m_id);
		out.writeDouble(m_long);
		out.writeDouble(m_lat);
		out.writeString(m_name);
		out.writeString(m_desc);
		out.writeString(m_startTime.toGMTString());
		out.writeString(m_endTime.toGMTString());
		out.writeInt(m_checkedInUsers);
		out.writeString(m_password);
	}

	public static final Parcelable.Creator<Event> CREATOR = new Parcelable.Creator<Event>() {
		public Event createFromParcel(Parcel in) {
			return new Event(in);
		}

		public Event[] newArray(int size) {
			return new Event[size];
		}
	};

	public int describeContents() {
		return 0;
	}

	private Event(Parcel in) {
		m_id = in.readInt();
		m_long = in.readDouble();
		m_lat = in.readDouble();
		m_name = in.readString();
		m_desc = in.readString();

		m_startTime = new Date(in.readString());
		m_endTime = new Date(in.readString());
		m_checkedInUsers = in.readInt();
		m_password = in.readString();
	}
}
